/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-05-23     Administrator       the first version
 */
#include "dlt645.h"
#include "rtthread.h"
#include "stdio.h"
#include "dlt645_port.h"
#include "board.h"
#include <drv_common.h>
#include <rtthread.h>

//----------MODBUS 多路复用引脚----------
#define DLT645_MAX_CH 4   // 4个modbus复用一个UART，其中通道4用于AI模组通信
#define DLT645_REG_MAX 20 // 最大解析数据项
#define DLT645_MAX_DEV 6  // 最大设备类型数
//----------MODBUS 通道索引-----------
#define DLT645_CH_1 1 // 通道1
#define DLT645_CH_2 2 // 通道2
#define DLT645_CH_3 3 // 通道3

#define DLT645_CH_SEL_A_PIN GET_PIN(D, 12) // 结合两个CD4052BPWR实现UART6 扩展成3个MODUBS 接口+1个AI模组
#define DLT645_CH_SEL_B_PIN GET_PIN(D, 13) // 结合两个CD4052BPWR实现UART6 扩展成3个MODUBS 接口+1个AI模组
#define DLT645_COM_DIR_PIN GET_PIN(D, 14)  // modbus收发方向控制引脚, HIGH = 发送， LOW = 接收
#define DLT645_COM_PWR_PIN GET_PIN(D, 15)  // modbus供电使能引脚，         HIGH = 给电， LOW = 断电

#define DLT645_UAT4_DIR_PIN GET_PIN(A, 2) // modbus收发方向控制引脚, HIGH = 发送， LOW = 接收
#define DLT645_UAT4_PWR_PIN GET_PIN(A, 3) // modbus供电使能引脚，         HIGH = 给电， LOW = 断电
///-----------------------------------------------------------
typedef enum
{
    flowwMeter_DLSD = 0x01, // 大连道盛流量计
    flowwMeter_JSBC = 0x02, // 江苏丙辰流量计 188协议

    eMeter_JSBC = 0x03, // 江苏丙辰电表 645协议
    eMeter_RANB = 0x04, // 睿安智邦电表 645协议

    recloseSW_TZ = 0x05, // 天正重合闸  645
    recloseSW_XW = 0x06, // 西屋重合闸  645
    recloseSW_ZT = 0x07, // 正泰重合闸  645

} e_mb_dev_type;


//--------------------------------------------------------------------
uint8_t dev_addr[6] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
// dlt645 采集测试标识符 （A相电压）
#define DLT645_2007_READ_TEST_CODE 0x02010100
#define DLT645_1997_READ_TEST_CODE 0xB611

#define DLT645_2007_PH_A_VOL_CODE 0x02010100            // A 相电压标识
#define DLT645_2007_PH_B_VOL_CODE 0x02010200            // B 相电压标识
#define DLT645_2007_PH_C_VOL_CODE 0x02010300            // C 相电压标识

#define DLT645_2007_PH_A_CUR_CODE 0x02020100            // A 相电流标识
#define DLT645_2007_PH_B_CUR_CODE 0x02020200            // B 相电流标识
#define DLT645_2007_PH_C_CUR_CODE 0x02020300            // C 相电流标识

#define DLT645_2007_PWR_FACT_CODE    0x02060000         // 总功率因数

#define DLT645_2007_DEV_TEMP_CODE    0x02800007         // 表内温度

#define DLT645_2007_ACT_ENRGY_CODE   0x00010000         // 正向有功总电能

#define DLT645_2007_DATE_CODE    0x04000101         // 日期及星期 不读
#define DLT645_2007_TIME_CODE    0x04000102         // 时间





//--------------------------------------------------------------------

void DLT645_mux_ctrlIO_init(void)
{

    rt_pin_mode(DLT645_CH_SEL_A_PIN, PIN_MODE_OUTPUT); // DLT645多路复用引脚
    rt_pin_mode(DLT645_CH_SEL_B_PIN, PIN_MODE_OUTPUT); // DLT645多路复用引脚
    rt_pin_mode(DLT645_COM_DIR_PIN, PIN_MODE_OUTPUT);  // DLT645多路复用引脚
    rt_pin_mode(DLT645_COM_PWR_PIN, PIN_MODE_OUTPUT);  // DLT645多路复用引脚

    rt_pin_mode(DLT645_UAT4_DIR_PIN, PIN_MODE_INPUT); // DLT645 UART4 方向控制引脚 配置成输入模式 防止影响AI 模组
    rt_pin_mode(DLT645_UAT4_PWR_PIN, PIN_MODE_INPUT); // DLT645 UART4 电源控制引脚 配置成输入模式 防止影响AI 模组
}

// ch_id 在内部做-1处理
void DLT645_ch_sel(uint8_t ch_id)
{
    uint8_t ch_nmbr = (ch_id - 1) & 0x03; // 保留0-3 低2位有效

    uint8_t sel_A_pin = ch_nmbr & 0x01;           // 通道号的bit0
    uint8_t sel_B_pin = (ch_nmbr & 0x02) ? 1 : 0; // 通道号的bit1

    rt_pin_write(DLT645_CH_SEL_A_PIN, sel_A_pin); // modubs通道选择
    rt_pin_write(DLT645_CH_SEL_B_PIN, sel_B_pin); // modubs通道选择
}

/*

PARITY_NONE PARITY_ODD PARITY_EVEN
 DATA_BITS_8    DATA_BITS_9

 STOP_BITS_1
*/

rt_bool_t DLT645_param_config(uint32_t baudRate, uint8_t parity, uint8_t dataBits, uint8_t stopBits)
{
    rt_device_t dev_uart = RT_NULL;
    struct rt_serial_device *uart_handle;

    dev_uart = rt_device_find(DLT645_SERIAL_NAME);
    if (dev_uart == RT_NULL)
    {
        /* can not find uart */
        return RT_FALSE;
    }
    else
    {
        uart_handle = (struct rt_serial_device *)dev_uart;
    }

    /* set serial configure parameter */
    uart_handle->config.baud_rate = baudRate;
    uart_handle->config.stop_bits = stopBits;

    uart_handle->config.parity = parity;
    uart_handle->config.data_bits = dataBits;

    /* set serial configure */
    uart_handle->ops->configure(uart_handle, &(uart_handle->config));

    return RT_TRUE;
}





/**
 * Name:    dlt645_start_read_data
 * Brief:   dlt645协议采集测试程序
 * Input:   None
 * Output:  None
 */
static float dlt645_start_read_data( uint32_t code)
{
    float result = 0;
    uint8_t read_buf[4];
    rt_memset(read_buf, 0, sizeof(read_buf));
    dlt645_set_addr(&dlt645, dev_addr);    // 设置从机地址
    dlt645_set_debug(&dlt645, 0);           // 设置debug模式


//     if(dlt645_read_data(&dlt645,DLT645_1997_READ_TEST_CODE,read_buf,DLT645_1997) > 0) //1997采集测试
    if (dlt645_read_data(&dlt645, code, read_buf, DLT645_2007) > 0) // 2007采集测试
    {
//        rt_kprintf("read result = : %.2f \r\n", *(float *)read_buf);
        memcpy(&result, read_buf, sizeof read_buf);
    }
    else{
        rt_kprintf("data read failure\r\n");
        result = -1;
    }

    return result;


}

/**
 * Name:    dlt645_entry
 * Brief:   dlt645协议测试线程
 * Input:   None
 * Output:  None
 */
static void dlt645_read_entry(void *param)
{
    float read_data = 0;
    DLT645_mux_ctrlIO_init(); // 初始化多路选择控制IO
    DLT645_ch_sel(1);         // 默认选择通道1
    // dlt645 硬件层初始化
    dlt645_port_init();
    while (1)
    {
        //------------CH1-电表--------------
        DLT645_ch_sel(1); // 默认选择通道1
        DLT645_param_config(2400, PARITY_EVEN, DATA_BITS_8, STOP_BITS_1);
        // 采集电压值
        read_data = dlt645_start_read_data(DLT645_2007_PH_A_VOL_CODE);
        rt_kprintf("PA VOL = : %.2f \r\n", read_data);
        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_PH_B_VOL_CODE);
//        rt_kprintf("PB VOL = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_PH_C_VOL_CODE);
//        rt_kprintf("PC VOL = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
//        // 采集电流值
//        read_data = dlt645_start_read_data(DLT645_2007_PH_A_CUR_CODE);
//        rt_kprintf("PA CUR = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_PH_B_CUR_CODE);
//        rt_kprintf("PB CUR = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_PH_C_CUR_CODE);
//        rt_kprintf("PC CUR = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_PWR_FACT_CODE);
//        rt_kprintf("PWR FACTOR = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
////        read_data = dlt645_start_read_data(DLT645_2007_DEV_TEMP_CODE);        //温度读取 -6.93e+28
////        rt_kprintf("DEV TEMP = : %.2f \r\n", read_data);
////        rt_thread_mdelay(1000);
//        read_data = dlt645_start_read_data(DLT645_2007_ACT_ENRGY_CODE);
//        rt_kprintf("ACTIVE ENERGY = : %.2f \r\n", read_data);
//        rt_thread_mdelay(1000);
    }
}

int create_dlt645sensor_read_thread(void)
{
    rt_thread_t tid;
    tid = rt_thread_create("dlt645", dlt645_read_entry, RT_NULL, 4096, 8, 20);
    if (tid != RT_NULL)
        rt_thread_startup(tid);
    return 0;
}
